package cnsatmsmart.automation.mmi.controller.IO;

import cnsatmsmart.automation.mmi.controller.Buffer.*;
import cnsatmsmart.automation.mmi.view.dialogs.listFlightView;
import cnsatmsmart.automation.mmi.view.layers.FlightLayer;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.table.DefaultTableModel;

/**
 * Kelas yang menggambar data pesawat di atas peta
 * @author SIK - PTIK, BPPT
 */
public class Painter implements Runnable
{
    /* atribut-atribut yang dimiliki oleh kelas Painter */
        private boolean ExitThread = false;
        private List<Flight> FlightList = new ArrayList<Flight>();
        private FlightList FlightData;
        private FlightLayer flightLayer;                                //FlightLayer untuk peta utama
        private FlightLayer flightLayer2;                               //FlightLayer untuk ZoomArea
        private DefaultTableModel model;                                //model untuk tabel list pesawat
        private listFlightView tableFlight;                             //tabel list pesawat
        private List<Integer> listRemove = new ArrayList<Integer>();    //list pesawat yang akan dihapus dari tabel list pesawat

        /**
         *
         */
        public boolean PrintList = false;
        
    /**
     * constructor - user defined constructor, no default constructor
     * @param flightdata buffer dari flight yang akan gambar
     * @param flightLayer layer flight pada peta utama
     * @param tableFlightView tabel list pesawat
     * @param flightLayer2 layer flight pada peta overview
     */
        public Painter (FlightList flightdata, FlightLayer flightLayer, FlightLayer flightLayer2, listFlightView tableFlightView)
        {
            this.FlightData = flightdata;
            this.flightLayer = flightLayer;
            this.flightLayer2 = flightLayer2;
            this.tableFlight = tableFlightView;
            this.model = tableFlightView.getModel();
        }

    /* method - method yang dibutuhkan untuk thread */
        /**
         * Keluar dari thread
         */
        public void Exit()
        {
            this.ExitThread = true;
        }

        public void run() {
            int row; 
            while (!ExitThread)
            {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Painter.class.getName()).log(Level.SEVERE, null, ex);
                }
               //No Reference, deep copy
               FlightList = FlightData.getFlightList();
               
               if (FlightList.isEmpty())
               {
                    flightLayer.setFlights(FlightList,true);
                    flightLayer2.setFlights(FlightList,false);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Painter.class.getName()).log(Level.SEVERE, null, ex);
                    }
               }
               else
               {
                   synchronized (FlightList)
                   {
                        for (int i = 0; i < FlightList.size(); i++)
                        {
                            //flight ditampilkan di JTable. ada yang ditambahkan, ada yang diupdate, dan ada yang dihapus
                            if (!searchCallSign(FlightList.get(i).getCallSign()))
                            {
                                //kalau ada pesawat baru maka ditambahkan pada listnya
                                model.addRow(getData(FlightList.get(i)));
                                tableFlight.getTable().setRowHeight(35);
                            }
                            else
                            {
                                //kalau pesawatnya masih ada pada flightlist, maka hanya diupdate saja
                                row = searchCallSignIdx(FlightList.get(i).getCallSign());

                                model.setValueAt(getStatusImage(FlightList.get(i)), row, 0);
                                model.setValueAt(getStateImage(FlightList.get(i)), row, 1);
                                model.setValueAt(FlightList.get(i).getLatitude(), row, 6);
                                model.setValueAt(FlightList.get(i).getLongitude(), row, 7);
                                model.setValueAt(FlightList.get(i).getAltitude(), row, 8);
                                model.setValueAt(FlightList.get(i).getVerticalrate(), row, 9);
                                model.setValueAt(FlightList.get(i).getTrackangle(), row, 10);
                                model.setValueAt(FlightList.get(i).getGroundSpeed(), row, 11);
                                model.setValueAt(FlightList.get(i).getstrLastUpdate(), row, 12);
                                model.setValueAt(FlightList.get(i).getTimeOfDay(), row, 13);
                            }

                            //mencari yang tidak ada pada flightlist tetapi ada pada table dan menghapusnya setiap 5 menit
                            diffList();
                            if (!listRemove.isEmpty())
                            {
                                //dihapus
                                for (int j=listRemove.size()-1; j>=0; --j)
                                {
                                    model.removeRow(listRemove.get(j));
                                }
                            }
                        }
                        flightLayer.setFlights(FlightList,true);
                        flightLayer2.setFlights(FlightList,false);
                        
                        if (PrintList)
                        {
                            PrintList = false;
                        }
                   }
               }
            }
        }

    /* method-method lain yang dimiliki oleh kelas Painter */
        /**
         * mengembalikan array objek atribut yang dimiliki oleh suatu flight
         * @param flight pesawat yang dikembalikan semua atributnya
         * @return Object[] - array dari seluruh atribut yang dimiliki oleh flight
         */
        private Object[] getData(Flight flight)
        {
            ImageIcon imageIcon;

            if (flight.getCountry() != null && !flight.getCountry().isEmpty())
                {imageIcon = new ImageIcon(getClass().getResource("/cnsatmsmart/resources/icon/"+flight.getCountry()+".png"));}
            else
                {imageIcon = new ImageIcon();}

            Object[] data = {getStatusImage(flight),
                            getStateImage(flight),
                            flight.getCode(),
                            flight.getCallSign(),
                            imageIcon,
                            flight.getCountry(),
                            flight.getLatitude(),
                            flight.getLongitude(),
                            flight.getAltitude(),
                            flight.getVerticalrate(),
                            flight.getTrackangle(),
                            flight.getGroundSpeed(),
                            flight.getstrLastUpdate(),
                            flight.getTimeOfDay()};
            return data;
        }

        /**
         * mengembalikan image status dari flight
         * @param flight pesawat yang diberikan
         * @return Object - objek image status pesawat
         */
        private Object getStatusImage (Flight flight)
        {
            ImageIcon statusIcon;
            if (!flight.getStatus())
                {statusIcon = new ImageIcon(getClass().getResource("/cnsatmsmart/resources/circle.png"));}
            else
                {statusIcon = new ImageIcon(getClass().getResource("/cnsatmsmart/resources/airplane.png"));}
            return statusIcon;
        }

        /**
         * mengembalikan image state dari flight
         * @param flight pesawat yang diberikan
         * @return Object - objek image status pesawat
         */
        private Object getStateImage(Flight flight)
        {
            ImageIcon stateIcon;
            if (flight.getState() == -1)
                {stateIcon = new ImageIcon(getClass().getResource("/cnsatmsmart/resources/arrow-down.png"));}
            else if (flight.getState() == 0)
                {stateIcon = new ImageIcon(getClass().getResource("/cnsatmsmart/resources/arrow.png"));}
            else
                {stateIcon = new ImageIcon(getClass().getResource("/cnsatmsmart/resources/arrow-up.png"));}
            return stateIcon;
        }

        /**
         * mencari pesawat dengan callSign pada tabel pesawat, mengembalikan true atau false
         * @param callSign - Call Sign yang dicari
         * @return true - jika ditemukan <br>
         *         false - jika tidak ditemukan
         */
        private boolean searchCallSign(String callSign)
        {
            boolean found = false;
            for (int i = 0; i<model.getRowCount(); ++i)
            {
                if (model.getValueAt(i, 3).equals(callSign))
                {
                    found = true;
                }
            }
            return found;
        }

        /**
         * mencari pesawat dengan callSign pada tabel pesawat, mengembalikan index dari tabel
         * @param callSign Call Sign yang dicari
         * @return -1 - jika tidak ditemukan <br>
         *         int - indekx dari tabel pesawat jika ditemukan
         */
        private int searchCallSignIdx(String callSign)
        {
            int idx = -1;
            for (int i = 0; i<model.getRowCount(); ++i)
            {
                if (model.getValueAt(i, 3).equals(callSign))
                {
                    idx = i;
                }
            }
            return idx;
        }

        /**
         * listRemove dikosongkan, kemudian di cari dari tabel yang tidak ada pada list pesawat dan sudah 5 menit tidak diupdate, ditambahkan pada listRemove
         */
        private void diffList()
        {
            listRemove.clear();
            boolean found = false;

            for (int i=0; i<model.getRowCount(); ++i)
            {
                for (int j=0; j<FlightList.size(); ++j)
                {
                    if (FlightList.get(j).getCallSign().equals(model.getValueAt(i, 3)))
                    {
                        found = true;
                    }
                }
                if (!found)
                {
                    String flightLastUpdate = model.getValueAt(i, 12).toString();
                    String[] flightTimeStr = flightLastUpdate.split(":");
                    String[] timeStr = Flight.getTimeNow().split(":");
                    int MinuteNow = Integer.parseInt(timeStr[1]);
                    if (flightTimeStr[0].equals(timeStr[0]) && Integer.parseInt(flightTimeStr[1])+5 <= MinuteNow && flightTimeStr[2].equals(timeStr[2]))
                    {
                        listRemove.add(i);
                    }
                }
                found = false;
            }
        }
}